import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;

/**
 * This class calculates all of the features of an e-mail and stores them.
 * 
 * @author
 * 
 */
public class DataBean {

	/**
	 * The collection of features that are used to classify emails
	 */
	private static ArrayList<String> features_list;
	private static String[] features = { "length", "num_words",
			"non_dictionary", "freq_stopwords", "non_charBased", "click",
			"viagra", "http", "make", "address", "our", "internet", "order",
			"business", "free", "your", "you", "money", "credit", "000",
			"mail", "receive", "will", "invoice", "payment", "meeting",
			"investment", "thanks", "#", "$", "!", "[", "(", ";", "@" };

	private static int freq_start_index = 2;

	static {
		features_list = new ArrayList<String>(Arrays.asList(features));
	}

	private String originalEmail;
	private String fileName;

	/**
	 * The true classification of the email
	 */
	private String classification;

	/**
	 * The predicted classification of the email
	 */
	private String prediction;

	/**
	 * An array of feature values for the email, features are organised
	 * according to their arrangement in the features array
	 */
	private double[] featureValues;

	public DataBean(String statString, String fileName,
			HashSet<String> dictionary, HashSet<String> stopwords) {
		originalEmail = statString;
		featureValues = new double[features.length];

		initialiseFeatures(dictionary, stopwords);
	}

	/**
	 * Initialises the feature values of the email
	 * 
	 * @param dictionary
	 *            - a dictionary of accepted words
	 * @param stopwords
	 *            - a dictionary of stop words
	 */
	public void initialiseFeatures(HashSet<String> dictionary,
			HashSet<String> stopwords) {

		int length = features_list.indexOf("length");
		featureValues[length] = originalEmail.length();

		String wordOnly = Util.removeJunk(originalEmail);
		String[] word = wordOnly.split("\\s");

		// Initialise the number of words
		int num_word_index = features_list.indexOf("num_words");
		if (word.length == 1 && word[0].equals("")) {
			featureValues[num_word_index] = 0;
		} else {
			featureValues[num_word_index] = word.length;

			// Initialise the frequencies of features
			initialiseFrequencyFeatures(word, dictionary, stopwords);
		}
	}

	/**
	 * Initialises the feature values that are based on frequency counts over
	 * the email
	 * 
	 * @param email
	 *            - the words of the email
	 * @param dictionary
	 *            - a dictionary of accepted words
	 * @param stopwords
	 *            - a dictionary of stop words
	 */
	public void initialiseFrequencyFeatures(String[] email,
			HashSet<String> dictionary, HashSet<String> stopwords) {

		int non_dict_index = features_list.indexOf("non_dictionary");
		int stopwords_index = features_list.indexOf("freq_stopwords");
		int non_charBased_index = features_list.indexOf("non_charBased");

		for (String word : email) {
			String wordLower = word.toLowerCase();

			// Update the word frequency counts for the current word
			int word_index = features_list.indexOf(wordLower);
			if (word_index >= 0) {
				featureValues[word_index]++;
			}

			// Update the non-dictionary word counts based on the current word
			if (!dictionary.contains(wordLower)) {
				featureValues[non_dict_index]++;
			}

			// Update the stop-word counts based on the current word
			if (stopwords.contains(wordLower)) {
				featureValues[stopwords_index]++;
			}

			// Update the non-character-based word counts based on the current
			// word
			if (!wordLower.matches("[a-z]*")) {
				featureValues[non_charBased_index]++;
			}

		}

		int num_word_index = features_list.indexOf("num_words");
		double num_words = featureValues[num_word_index];

		// normalise features by the number of words in the email
		for (int i = freq_start_index; i < featureValues.length; i++) {
			featureValues[i] /= num_words;
		}

	}

	public String[] getFeatureNames() {
		return features;
	}

	public double[] getFeatureValues() {
		return featureValues;
	}

	public String getOriginal() {
		return originalEmail;
	}

	public String getClassification() {
		return classification;
	}

	public String getPrediction() {
		return prediction;
	}

	public void setClassification(String classification) {
		this.classification = classification;
	}

	public void setPredicted(String prediction) {
		this.prediction = prediction;
	}

	/**
	 * Returns a string representation of the DataBean The string representation
	 * is used to train machine learning models
	 */
	public String toString() {
		String separator = ",";

		String attributes = "";
		for (double feature : featureValues) {
			attributes += feature + separator;
		}
		return attributes + separator + getClassification();
	}

	public void setFileName(String fileName) {
		this.fileName = fileName;
	}

	public String getFileName() {
		return fileName;
	}

	public int getLength() {
		return 0;
	}

}
